/*
 * @Author: your name
 * @Date: 2020-04-03 11:07:47
 * @LastEditTime: 2020-04-04 21:02:28
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \W+compiler-CMake\src\SemanticAnalyzer.cpp
 */
#include "../include/SemanticAnalyzer.h"

ifstream input_SyntacticInput_S("SyntacticInput_S.txt");
ifstream input_LexicalOutput_S("LexicalOutput_S.txt");
ifstream input_Token_S("TOKEN_S.txt");
ofstream output_ACTION_S;
ofstream output_GOTO_S;
ofstream output_FIRST_S;
ofstream output_PARSER_S;
ofstream output_QUAD_S;

// set<char> Item::final;  // 全局静态变量
// set<char> Item::unFinal;
// set<char> Item::allSymbol;

int delimiterNumS_S = 9;

int identNum = 0;

//界符
const char delimiterS_S[20] = {',', '(', ')', '{', '}', ';'};  //界符

/**
 * @description: 展示 ident表
 * @param {type}
 * @return:
 */
void LrS::showIdent()
{
    vector<IdentNode>::iterator it = ident_ALL.begin();
    for (; it != ident_ALL.end(); it++) {
        cout << "sourceId : " << (*it).sourceId << " newId : " << (*it).newId
             << endl;
    }
}
/**
 * @description:输出 四元组
 * @param {type}
 * @return:
 */
void LrS::showQuad()
{
    vector<Quad>::iterator it = quad_ALL.begin();
    for (; it != quad_ALL.end(); it++) {
        cout << "<" << (*it).op << " , " << (*it).arg1 << " , " << (*it).arg2
             << " , " << (*it).result << ">" << endl;
        output_QUAD_S << "<" << (*it).op << " , " << (*it).arg1 << " , "
                      << (*it).arg2 << " , " << (*it).result << ">" << endl;
    }
}

/**
 * @description: 实现对变量的检查
 * @param {type}
 * @return:
 */
bool LrS::isfindIdent(string name)
{
    // vector<IdentNode>        ident_ALL;
    vector<IdentNode>::iterator it = ident_ALL.begin();
    for (; it != ident_ALL.end(); it++) {
        if ((*it).sourceId == name) {
            return true;
        }
    }
    return false;
}

string LrS::findIdentbyName(string name)
{
    vector<IdentNode>::iterator it = ident_ALL.begin();
    for (; it != ident_ALL.end(); it++) {
        if ((*it).sourceId == name) {
            return (*it).newId;
        }
    }
    return "";
}

/**
 * @description: 返回一个新的变量名
 * @param {type}
 * @return:
 */
string LrS::newIdent()
{
    string output = "";
    output        = "t" + to_string(identNum);
    identNum++;
    return output;
}
/**
 * @description:语义分析
 * @param {type}
 * @return:
 */
void LrS::parser_S()
{
    // map<int, vector<string>> inputToken_ALL;
    // vector<Quad> quad_ALL;
    // vector<char> inputStack_S;  //输入栈
    // vector<int>  lineStack_S;   //行数栈

    // cout << "parser_S" << endl;
    vector<char>::reverse_iterator it_input_all = inputStack_S.rbegin();  //反向

    vector<int>::iterator it_line_all = lineStack_S.begin();

    string inputS;
    for (; it_input_all != inputStack_S.rend(); it_input_all++) {
        inputS += (*it_input_all);
    }
    // cout << "inputS : " << inputS << endl;

    inputStack_S.pop_back();  //去除#
    lineStack_S.pop_back();

    bool begin   = false;
    int  nowDeal = 0;
    while (inputS.size() != 0) {
        if ((inputS[nowDeal] == 't' && inputS[nowDeal + 2] != '(')) {
            //说明为 tz; tz=xxx
            std::size_t it = inputS.find(';');
            string deal = inputS.substr(0, it + 1);  //得到了处理的对象
            // cout << "DEAL : " << deal << endl;

            int lineNow = lineStack_S.back();
            int type_S;
            //处理主体:
            if (deal.size() == 3) {  //处理 tz; 的情况

                string type = inputToken_ALL[lineNow][0];
                string name = inputToken_ALL[lineNow][1];
                if (isfindIdent(name) == true) {
                    cout << "Error Line : " << lineNow << " -> 变量" << name
                         << "重复定义" << endl;
                    output_PARSER_S << "Error Line : " << lineNow << " -> 变量"
                                    << name << "重复定义" << endl;
                }
                else {
                    string newId = newIdent();
                    if (type == "int") {
                        type_S = 0;
                    }
                    else {
                        type_S = 1;
                    }
                    IdentNode node;
                    node.identType = type_S;
                    node.sourceId  = name;
                    node.newId     = newId;
                    ident_ALL.push_back(node);
                }
            }
            else if (deal.size() == 5)  //处理 tz = y; 或 tz = z;
            {
                string type = inputToken_ALL[lineNow][0];
                string name = inputToken_ALL[lineNow][1];
                string num  = inputToken_ALL[lineNow][3];  // y的值
                if (deal[3] == 'y') {                      //处理 tz=y;

                    if (isfindIdent(name) == true) {
                        cout << "Error Line : " << lineNow << " -> 变量" << name
                             << "重复定义" << endl;
                        output_PARSER_S << "Error Line : " << lineNow
                                        << " -> 变量" << name << "重复定义"
                                        << endl;
                    }
                    else {
                        string newId = newIdent();
                        if (type == "int") {
                            type_S = 0;
                        }
                        else {
                            type_S = 1;
                        }
                        if (((type_S = 0) && (num.find('"') != string::npos)) ||
                            // int 且找到了 "
                            (type_S = 1 && (num.find('"') == string::npos))) {
                            // string 且没找到"
                            cout << "Error Line : " << lineNow << " -> 变量"
                                 << name << "赋值类型错误" << endl;
                            output_PARSER_S << "Error Line : " << lineNow
                                            << " -> 变量" << name
                                            << "赋值类型错误" << endl;
                        }
                        else {
                            //添加到变量表
                            IdentNode node;
                            node.identType = type_S;
                            node.sourceId  = name;
                            node.newId     = newId;
                            ident_ALL.push_back(node);

                            //添加到 四元组表
                            Quad q;
                            q.op     = "=";
                            q.arg1   = num;
                            q.arg2   = "-";
                            q.result = newId;
                            quad_ALL.push_back(q);
                        }
                    }
                }
                else {
                    string arg2name = inputToken_ALL[lineNow][2];  // z的值
                    if (findIdentbyName(arg2name) != "") {         //找到了
                        string arg2Id = findIdentbyName(arg2name);
                        if (isfindIdent(name) == true) {
                            cout << "Error Line : " << lineNow << " -> 变量"
                                 << name << "重复定义" << endl;
                            output_PARSER_S << "Error Line : " << lineNow
                                            << " -> 变量" << name << "重复定义"
                                            << endl;
                        }
                        else {
                            string newId = newIdent();
                            if (type == "int") {
                                type_S = 0;
                            }
                            else {
                                type_S = 1;
                            }
                            //添加到变量表
                            IdentNode node;
                            node.identType = type_S;
                            node.sourceId  = name;
                            node.newId     = newId;
                            ident_ALL.push_back(node);

                            //添加到 四元组表
                            Quad q;
                            q.op     = "=";
                            q.arg1   = arg2Id;
                            q.arg2   = "-";
                            q.result = newId;
                        }
                    }
                    else {
                        cout << "Error Line : " << lineNow << " -> 变量"
                             << arg2name << "未定义" << endl;
                        output_PARSER_S << "Error Line : " << lineNow
                                        << " -> 变量" << arg2name << "未定义"
                                        << endl;
                    }
                }
            }
            else if (deal.size() == 7)
            //处理 tz = y+y ; 或者 tz=z+y; 或者  tz=y+z 或者 tz = z+z;
            {
                string type = inputToken_ALL[lineNow][0];
                string name = inputToken_ALL[lineNow][1];
                string arg1 = inputToken_ALL[lineNow][3];
                string op   = inputToken_ALL[lineNow][4];
                string arg2 = inputToken_ALL[lineNow][5];
                if (deal[3] == 'y' && deal[5] == 'y') {  // tz=y+y;
                    if (isfindIdent(name) == true) {
                        cout << "Error Line : " << lineNow << " -> 变量" << name
                             << "重复定义" << endl;
                        output_PARSER_S << "Error Line : " << lineNow
                                        << " -> 变量" << name << "重复定义"
                                        << endl;
                    }
                    else {
                        //先处理 y+y
                        string newId1 = newIdent();
                        type_S        = 0;
                        //添加到变量表
                        IdentNode node;
                        node.identType = type_S;
                        node.sourceId  = "";
                        node.newId     = newId1;
                        ident_ALL.push_back(node);

                        //添加到 四元组表
                        Quad q;
                        q.op     = op;
                        q.arg1   = arg1;
                        q.arg2   = arg2;
                        q.result = newId1;
                        quad_ALL.push_back(q);

                        //再处理 tz
                        string newId2 = newIdent();
                        type_S        = 0;

                        IdentNode node2;
                        node2.identType = type_S;
                        node2.sourceId  = name;
                        node2.newId     = newId2;
                        ident_ALL.push_back(node2);

                        Quad q2;
                        q2.op     = "=";
                        q2.arg1   = newId1;
                        q2.arg2   = "-";
                        q2.result = newId2;
                        quad_ALL.push_back(q2);
                    }
                }
                else if ((deal[3] == 'z' && deal[5] == 'y') ||
                         (deal[3] == 'y' && deal[5] == 'z')) {
                    string newId1 = newIdent();
                    if (deal[3] == 'z') {  // arg1 为变量
                        // cout << "arg1 : " << arg1 << endl;

                        if (findIdentbyName(arg1) != "") {  //找到了

                            type_S = 0;
                            //添加到变量表
                            IdentNode node;
                            node.identType = type_S;
                            node.sourceId =
                                (findIdentbyName(arg1) + "+" + arg2);
                            node.newId = newId1;
                            ident_ALL.push_back(node);

                            //添加到 四元组表
                            Quad q;
                            q.op     = op;
                            q.arg1   = findIdentbyName(arg1);
                            q.arg2   = arg2;
                            q.result = newId1;
                            quad_ALL.push_back(q);
                        }
                        else {
                            cout << "Error Line : " << lineNow << " -> 变量"
                                 << arg1 << "未定义" << endl;
                            output_PARSER_S << "Error Line : " << lineNow
                                            << " -> 变量" << arg1 << "未定义"
                                            << endl;
                        }
                    }
                    else if (deal[5] == 'z') {
                        if (findIdentbyName(arg2) != "") {  //找到了
                            type_S = 0;
                            //添加到变量表
                            IdentNode node;
                            node.identType = type_S;
                            node.sourceId =
                                (arg1 + "+" + findIdentbyName(arg2));
                            node.newId = newId1;
                            ident_ALL.push_back(node);

                            //添加到 四元组表
                            Quad q;
                            q.op     = op;
                            q.arg1   = arg1;
                            q.arg2   = findIdentbyName(arg1);
                            q.result = newId1;
                            quad_ALL.push_back(q);
                        }
                        else {
                            cout << "Error Line : " << lineNow << " -> 变量"
                                 << arg1 << "未定义" << endl;
                            output_PARSER_S << "Error Line : " << lineNow
                                            << " -> 变量" << arg1 << "未定义"
                                            << endl;
                        }
                    }

                    //最后判断 tz的z
                    if (isfindIdent(name) == true) {
                        cout << "Error Line : " << lineNow << " -> 变量" << name
                             << "重复定义" << endl;
                        output_PARSER_S << "Error Line : " << lineNow
                                        << " -> 变量" << name << "重复定义"
                                        << endl;
                    }
                    else {
                        string newIdname = newIdent();
                        type_S           = 0;
                        //添加到变量表
                        IdentNode node;
                        node.identType = type_S;
                        node.sourceId  = name;
                        node.newId     = newIdname;
                        ident_ALL.push_back(node);

                        //添加到 四元组表
                        Quad q;
                        q.op     = "=";
                        q.arg1   = newId1;
                        q.arg2   = "-";
                        q.result = newIdname;
                        quad_ALL.push_back(q);
                    }
                }
                else {  // tz = z+z
                    if (findIdentbyName(arg1) == "") {
                        cout << "Error Line : " << lineNow << " -> 变量" << arg1
                             << "未定义" << endl;
                        output_PARSER_S << "Error Line : " << lineNow
                                        << " -> 变量" << arg1 << "未定义"
                                        << endl;
                        exit(0);
                    }
                    else if (findIdentbyName(arg2) == "") {
                        cout << "Error Line : " << lineNow << " -> 变量" << arg2
                             << "未定义" << endl;
                        output_PARSER_S << "Error Line : " << lineNow
                                        << " -> 变量" << arg2 << "未定义"
                                        << endl;
                        exit(0);
                    }
                    else {
                        //表示arg1 arg2 都已定义
                        //判断name是否已经定义
                        if (isfindIdent(name) == true) {
                            cout << "Error Line : " << lineNow << " -> 变量"
                                 << name << "重复定义" << endl;
                            output_PARSER_S << "Error Line : " << lineNow
                                            << " -> 变量" << name << "重复定义"
                                            << endl;
                        }
                        else {
                            string newId1 = newIdent();
                            type_S        = 0;
                            //添加到变量表
                            IdentNode node;
                            node.identType = type_S;
                            node.sourceId  = name;
                            node.newId     = newId1;
                            ident_ALL.push_back(node);

                            //添加到 四元组表
                            Quad q;
                            q.op     = op;
                            q.arg1   = findIdentbyName(arg1);
                            q.arg2   = findIdentbyName(arg2);
                            q.result = newId1;
                            quad_ALL.push_back(q);
                        }
                    }
                }
            }
            //处理主体结束
            for (int dealSize = 0; dealSize < deal.size(); dealSize++) {
                // cout << lineStack_S.back() << " ";
                lineStack_S.pop_back();
                inputS.erase(inputS.begin());
            }
            cout << endl;
        }
        else if (inputS[nowDeal] == 'z' && inputS[nowDeal + 1] == '=') {
            //分析 z=y op y;z= z op y; z = z op z; z=y op z;
            std::size_t it = inputS.find(';');
            string deal = inputS.substr(0, it + 1);  //得到了处理的对象
            // cout << "DEAL : " << deal << endl;

            int lineNow = lineStack_S.back();
            int type_S;
            //主体
            string name = inputToken_ALL[lineNow][0];
            string arg1 = inputToken_ALL[lineNow][2];
            string op   = inputToken_ALL[lineNow][3];
            string arg2 = inputToken_ALL[lineNow][4];

            // z=y+y;
            if (deal[2] == 'y' && deal[4] == 'y') {
                if (findIdentbyName(name) != "") {
                    //找到了 z
                    string newIdyy = newIdent();
                    type_S         = 0;

                    //添加yy 到变量表
                    IdentNode nodeyy;
                    nodeyy.identType = type_S;
                    nodeyy.sourceId  = "";
                    nodeyy.newId     = newIdyy;
                    ident_ALL.push_back(nodeyy);

                    Quad qyy;
                    qyy.op     = op;
                    qyy.arg1   = arg1;
                    qyy.arg2   = arg2;
                    qyy.result = findIdentbyName(name);
                    quad_ALL.push_back(qyy);

                    Quad q;
                    q.op     = "=";
                    q.arg1   = newIdyy;
                    q.arg2   = "-";
                    q.result = findIdentbyName(name);
                    quad_ALL.push_back(q);
                }
                else {
                    //未找到 z
                    cout << "Error Line : " << lineNow << " -> 变量" << name
                         << "未定义" << endl;
                    output_PARSER_S << "Error Line : " << lineNow << " -> 变量"
                                    << name << "未定义" << endl;
                }
            }
            else if ((deal[2] == 'z' && deal[4] == 'y') ||
                     (deal[4] == 'z' && deal[2] == 'y')) {
                // z=z+y z=y+z
                if (deal[2] == 'z') {  // z=z+y
                    if (findIdentbyName(arg1) != "") {
                        //找到了 z
                        if (findIdentbyName(name) != "") {
                            //找到了 z
                            string newIdyy = newIdent();
                            type_S         = 0;

                            //添加yy 到变量表
                            IdentNode nodeyy;
                            nodeyy.identType = type_S;
                            nodeyy.sourceId  = "";
                            nodeyy.newId     = newIdyy;
                            ident_ALL.push_back(nodeyy);

                            Quad qyy;
                            qyy.op     = op;
                            qyy.arg1   = findIdentbyName(arg1);
                            qyy.arg2   = arg2;
                            qyy.result = newIdyy;
                            quad_ALL.push_back(qyy);

                            Quad q;
                            q.op     = "=";
                            q.arg1   = newIdyy;
                            q.arg2   = "-";
                            q.result = findIdentbyName(name);
                            quad_ALL.push_back(q);
                        }
                        else {
                            //未找到 z
                            cout << "Error Line : " << lineNow << " -> 变量"
                                 << name << "未定义" << endl;
                            output_PARSER_S << "Error Line : " << lineNow
                                            << " -> 变量" << name << "未定义"
                                            << endl;
                        }
                    }
                    else {
                        //未找到 z
                        cout << "Error Line : " << lineNow << " -> 变量" << arg1
                             << "未定义" << endl;
                        output_PARSER_S << "Error Line : " << lineNow
                                        << " -> 变量" << arg1 << "未定义"
                                        << endl;
                    }
                }
                else {
                    if (findIdentbyName(arg2) != "") {
                        //找到了 z
                        if (findIdentbyName(name) != "") {
                            //找到了 z
                            string newIdyy = newIdent();
                            type_S         = 0;

                            //添加yy 到变量表
                            IdentNode nodeyy;
                            nodeyy.identType = type_S;
                            nodeyy.sourceId  = "";
                            nodeyy.newId     = newIdyy;
                            ident_ALL.push_back(nodeyy);

                            Quad qyy;
                            qyy.op     = op;
                            qyy.arg1   = arg1;
                            qyy.arg2   = findIdentbyName(arg2);
                            qyy.result = newIdyy;
                            quad_ALL.push_back(qyy);

                            Quad q;
                            q.op     = "=";
                            q.arg1   = newIdyy;
                            q.arg2   = "-";
                            q.result = findIdentbyName(name);
                            quad_ALL.push_back(q);
                        }
                        else {
                            //未找到 z
                            cout << "Error Line : " << lineNow << " -> 变量"
                                 << name << "未定义" << endl;
                            output_PARSER_S << "Error Line : " << lineNow
                                            << " -> 变量" << name << "未定义"
                                            << endl;
                        }
                    }
                    else {
                        //未找到 z
                        cout << "Error Line : " << lineNow << " -> 变量" << arg2
                             << "未定义" << endl;
                        output_PARSER_S << "Error Line : " << lineNow
                                        << " -> 变量" << arg2 << "未定义"
                                        << endl;
                    }
                }
            }
            else {  // z=z+z
                if (findIdentbyName(arg1) == "") {
                    cout << "Error Line : " << lineNow << " -> 变量" << arg1
                         << "未定义" << endl;
                    output_PARSER_S << "Error Line : " << lineNow << " -> 变量"
                                    << arg1 << "未定义" << endl;
                }
                else if (findIdentbyName(arg2) == "") {
                    cout << "Error Line : " << lineNow << " -> 变量" << arg2
                         << "未定义" << endl;
                    output_PARSER_S << "Error Line : " << lineNow << " -> 变量"
                                    << arg2 << "未定义" << endl;
                }
                else if (findIdentbyName(name) == "") {
                    cout << "Error Line : " << lineNow << " -> 变量" << name
                         << "未定义" << endl;
                    output_PARSER_S << "Error Line : " << lineNow << " -> 变量"
                                    << name << "未定义" << endl;
                }
                else {
                    string newIdyy = newIdent();
                    type_S         = 0;

                    //添加yy 到变量表
                    IdentNode nodeyy;
                    nodeyy.identType = type_S;
                    nodeyy.sourceId  = "";
                    nodeyy.newId     = newIdyy;
                    ident_ALL.push_back(nodeyy);

                    Quad qyy;
                    qyy.op     = op;
                    qyy.arg1   = findIdentbyName(arg1);
                    qyy.arg2   = findIdentbyName(arg2);
                    qyy.result = newIdyy;
                    quad_ALL.push_back(qyy);

                    Quad q;
                    q.op     = "=";
                    q.arg1   = newIdyy;
                    q.arg2   = "-";
                    q.result = findIdentbyName(name);
                    quad_ALL.push_back(q);
                }
            }

            // end
            for (int dealSize = 0; dealSize < deal.size(); dealSize++) {
                // cout << lineStack_S.back() << " ";
                lineStack_S.pop_back();
                inputS.erase(inputS.begin());
            }
            cout << endl;
        }
        else {
            nowDeal = 0;
            inputS.erase(inputS.begin());
            // cout << "else pop line : " << lineStack_S.back() << endl;
            lineStack_S.pop_back();
        }
    }
}
void LrS::addItem(string s)
{
    G.addItem(s);
}

void LrS::getInputStack(string input)
{
    //此处可以使用文件读入形式
    // input_file
    // cout << "LRS getInputStack" << endl;
    // cout << "读入 输入栈" << endl;
    inputStack.push_back('#');
    stateStack.push_back(0);
    for (int i = input.length() - 1; i >= 0; i--) {
        inputStack.push_back(input[i]);
    }

    //获取 行数
    string inToken;
    string temp;
    //原source中代码
    string sourceId;

    int  line;
    int  i, j;
    bool begin = true;

    j = 0;

    // vector<vector<string>>
    // inputToken_ALL初始化
    inputToken_ALL.clear();

    vector<string> one2all;

    lineStack.push_back(0);
    while (getline(input_Token_S, inToken)) {
        // cout << inToken << endl;
        temp = stringCut(inToken, 7, 9);
        line = stoi(stringCut(inToken, 1, 3));
        if (begin == true) {
            j     = line;
            begin = false;
        }
        // cout << "line : " << line << endl;
        if (temp == ">=" || temp == "<=" || temp == "==" || temp == "&&" ||
            temp == "||" || temp == "+=" || temp == "-=") {
            lineStack.push_back(line);
            lineStack.push_back(line);
        }
        else {
            lineStack.push_back(line);
        }

        //获取源代码中的值
        sourceId = inToken.substr(inToken.rfind(',') + 1,
                                  inToken.rfind('>') - 1 - inToken.rfind(','));
        // cout << "line : " << line;
        // cout << "sourceId : " << sourceId << endl;

        if (j != line) {
            inputToken_ALL[j] = (one2all);

            j = line;
            one2all.clear();
        }
        //行数
        one2all.push_back(sourceId);
    }

    reverse(lineStack.begin(), lineStack.end());

    // cout << "inputToken_ALL : " << endl;
    vector<int>::iterator    line_it;
    vector<string>::iterator it;

    i = 0;
    for (; i < inputToken_ALL.size(); i++) {
        if (!inputToken_ALL[i].empty()) {
            // cout << "line : " << i << "  ";
            it = inputToken_ALL[i].begin();
            for (; it != inputToken_ALL[i].end(); it++) {
                // cout << *it << " ";
            }
            // cout << endl;
        }
    }

    inputStack_S = inputStack;
    lineStack_S  = lineStack;
    // cout << "反向输出 inputStack : " << endl;
    // showInputStack();
}

void LrS::showInputStack()
{
    vector<char>::reverse_iterator it = inputStack.rbegin();
    for (; it != inputStack.rend(); ++it) {
        cout << (*it);
        output_PARSER_S << *it;
    }
}

void LrS::showStateStack()
{
    vector<int>::iterator it = stateStack.begin();
    for (; it != stateStack.end(); it++) {
        cout << *it;
        output_PARSER_S << *it;
    }
}

/**
 * @description: 展示分析栈
 * @param {type}
 * @return:
 */
void LrS::showAnalyzeStack()
{
    vector<char>::iterator it = analyzeStack.begin();
    for (; it != analyzeStack.end(); it++) {
        cout << *it;
        output_PARSER_S << *it;
    }
}

set<char> LrS::getFirst(string& str)
{
    int i = 0;

    if (str.length() == 0) {  // X->@
        set<char> a;
        a.insert('@');
        return a;
    }
    else if (str.length() == 1) {  // X->a
        //判断是否为终结符
        if (G.final.find(str[0]) != G.final.end() || str[0] == '#') {
            set<char> a;
            a.insert(str[0]);
            return a;
        }
        else if (FIRST[str[0]].size() != 0) {  // X->A
            //判断 FIRST中是否存在 以计算过的 first 集
            return FIRST[str[0]];
        }
        else {
            vector<Production>::iterator it = G.production.begin();
            for (; it != G.production.end(); it++) {
                //查找产生式 右部拥有左部非终结符的产生式
                if ((*it).proBegin == str[0]) {
                    string::size_type isExist =
                        (*it).proEnd.find((*it).proBegin);

                    // if (isExist != string::npos) {
                    //     if (isExist == 0) {  //存在左递归
                    //         continue;
                    //     }
                    //     else {
                    //         string temp = stringCut((*it).proEnd, 0,
                    //         isExist); set<char> a; a.insert('@'); if
                    //         (getFirst(temp) == a) {
                    //             continue;
                    //         }
                    //     }
                    // }

                    set<char> tempF = getFirst((*it).proEnd);

                    // cout << "getFirst : " << (*it).proBegin << endl;
                    FIRST[str[0]].insert(tempF.begin(), tempF.end());
                }
            }
            return FIRST[str[0]];
        }
    }
    else {  // X->ABCD等
        set<char> output;
        for (i = 0; i < str.length(); i++) {
            string    a      = char2string(str[i]);
            set<char> tempFF = getFirst(a);  //逐个符号求 getFirst

            if (tempFF.find('@') != tempFF.end() && str.length() - 1 != i) {
                //若存在 @ 则删除@ 并加入output 并进行 下一个字符的getFirst

                // set<char>::iterator itshow = tempFF.begin();
                //  cout << "getFirst-X1X2X3-可为空 : " << a << "first : ";
                // for (; itshow != tempFF.end(); itshow++) {
                //     cout << *itshow << " ";
                // }
                // cout << endl;

                tempFF.erase(tempFF.find('@'));
                output.insert(tempFF.begin(), tempFF.end());
            }
            else {
                //若tempFF中 没有 @ 或 str 为到最后一位
                // getFirst 完成
                output.insert(tempFF.begin(), tempFF.end());
                break;
            }
        }
        set<char>::iterator outputshow = output.begin();
        // cout << "getFirst-end output : ";
        for (; outputshow != output.end(); outputshow++) {
            // cout << *outputshow << " ";
        }
        // cout << endl;

        return output;
    }
}

Item LrS::eclosure(Item I)
{
    // cout << "eclosure--begin" << endl;
    // G.show();
    // cout << "I.show()" << endl;
    // I.show();

    if (I.production.size() == 0) {
        // cout << "Lr eclosure I为空" << endl;
        return I;
    }

    Production pStart = I.production[0];

    int i = 0;
    int j = 0;
    for (i = 0; i < I.production.size(); i++) {
        int ppoint = 0;

        Production ptemp = I.production[i];
        // ptemp.show();

        // Production ptemp=pStart;

        if (((ppoint = ptemp.proEnd.find('.')) != string::npos) &&
            (ppoint != ptemp.proEnd.length() - 1) &&
            (G.unFinal.find(ptemp.proEnd[ppoint + 1])) !=
                G.unFinal.end()) {  //确保找到的 '.' 的位置不为 最后 且

            // cout << "ppoint : " << ppoint << endl;

            char a = ptemp.proEnd[ppoint + 1];  //获得产生式右部的 .右边的符号
            // cout << a << endl;
            if (G.final.find(a) != G.final.end()) {  //若符号a 为终结符
                // cout << "unFinal" << endl;
                if (a == '@') {  //空
                    swap(I.production[i].proEnd[ppoint],
                         I.production[i].proEnd[ppoint + 1]);
                    continue;
                }
            }
            // cout << "no" << endl;

            // 若为非终结符 则：若项目[A→α·Bβ,a]属于CLOSURE(I)，
            // B→ξ是一个产生式，那么，对于FIRST（βa）中的每一个终结符b，
            //如果[B→·ξ，b]原来不在CLOSURE(I)中，则把它加进去；
            string f =
                stringCut(ptemp.proEnd, ppoint + 2, ptemp.proEnd.length());
            // cout << "f : " << f << endl;

            set<char> new_additionalSymbol =
                {};  // 求 新的 产生式的每一个终结符b

            set<char>::iterator it = ptemp.additionalSymbol.begin();
            for (; it != ptemp.additionalSymbol.end(); it++) {
                // cout << "for1" << endl;
                string a  = char2string((*it));
                string in = f + a;
                // cout << in << endl;
                set<char> temp = getFirst(in);
                new_additionalSymbol.insert(temp.begin(), temp.end());
            }

            // for (set<char>::iterator ittest = new_additionalSymbol.begin();
            //      ittest != new_additionalSymbol.end(); ittest++) {
            //     cout << (*ittest) << endl;
            // }

            //将找的的产生加入到项目集
            // cout << G.production.size() << endl;
            for (vector<Production>::iterator itProduction =
                     G.production.begin();
                 itProduction != G.production.end(); ++itProduction) {
                // cout << "for2" << endl;
                if ((*itProduction).proBegin == a)  //有问题 比较谁 与 谁相等~
                {
                    // cout << "proBegin = " << a << endl;
                    Production temp = *itProduction;
                    if (temp.proEnd[0] == '@') {
                        temp.proEnd = '.' + temp.proEnd;
                        swap(temp.proEnd[0], temp.proEnd[1]);
                    }
                    else {
                        temp.proEnd = '.' + temp.proEnd;
                        // cout << "temp.proEnd : " << temp.proEnd << endl;
                    }

                    // cout << temp.proBegin << "->" << temp.proEnd << endl;

                    //在 I 中搜索是否有相同的 产生式
                    // vector<Production>::iterator itI =
                    //     find(I.production.begin(), I.production.end(), temp);

                    bool isFindInG = false;

                    vector<Production>::iterator itI = I.production.begin();
                    for (; itI != I.production.end(); itI++) {
                        if (((*itI).proBegin == temp.proBegin) &&
                            ((*itI).proEnd == temp.proEnd)) {
                            isFindInG = true;
                            break;
                        }
                    }

                    if (isFindInG) {
                        // cout << temp.proBegin << "->" << temp.proEnd << endl;
                        //若找到相同的产生式，则添加
                        //附加终结符
                        // cout << "same" << endl << endl;
                        itI->additionalSymbol.insert(
                            new_additionalSymbol.begin(),
                            new_additionalSymbol.end());
                    }
                    else {  //若不存在，则添加新的产生式 以及其 附加终结符
                        // cout << "no same" << endl << endl;
                        temp.additionalSymbol.insert(
                            new_additionalSymbol.begin(),
                            new_additionalSymbol.end());
                        I.production.push_back(temp);
                    }
                }
            }
        }

        // for (j = 0; j < I.production.size(); j++) {
        //     if (I.production[j].isEclosure == false) {
        //         pStart = I.production[j];
        //     }
        // }
    }
    // I.show();
    // cout << endl;
    // cout << "eclosure--end" << endl;
    return I;
}

Item LrS::Go(Item I, char X)
{
    //根据课本来
    Item J;

    if (I.production.size() == 0 || X == '@') {
        //项目集为空 或@ 返回空项目集
        return J;
    }

    vector<Production>::iterator it = I.production.begin();
    for (; it != I.production.end(); it++) {
        string end    = (*it).proEnd;
        int    ppoint = end.find('.');
        if (end[ppoint + 1] == X) {
            swap(end[ppoint], end[ppoint + 1]);
            // cout << end << endl;
            Production temp =
                Production((*it).proBegin, end, (*it).additionalSymbol);
            J.production.push_back(temp);
        }
    }
    return eclosure(J);
}

void LrS::itemDFA()
{
    // cout << "itemDFA--begin" << endl;

    //设置 $->S,#
    Item begin;

    set<char> symbolBegin;
    symbolBegin.insert('#');
    Production S = Production('$', '.' + char2string(G.production[0].proBegin),
                              symbolBegin);
    S.isEclosure = true;
    begin.production.push_back(S);

    //项目集规范族 添加 初始 $->S,#
    program.push_back(eclosure(begin));

    int size = 0;
    while (size != program.size()) {  //当没有新的项目集加入时 停止
        size = program.size();
        for (int i = 0; i < program.size(); i++) {
            Item temp = program[i];
            for (set<char>::iterator itSymbol = G.allSymbol.begin();
                 itSymbol != G.allSymbol.end(); itSymbol++) {
                // cout << "itemDFA-Go-symbol : " << *itSymbol << endl;
                Item next = Go(temp, (*itSymbol));
                if (next.production.size() != 0) {
                    //判断 项目集规范族中 是否存在 求得的 next
                    vector<Item>::iterator idx =
                        find(program.begin(), program.end(), next);
                    if (idx != program.end()) {
                        //找到了重复的 Item
                        GOTO[make_pair(i, (*itSymbol))] =
                            distance(program.begin(), idx);
                    }
                    else {
                        //没有重复的 Item
                        program.push_back(next);
                        GOTO[make_pair(i, (*itSymbol))] =
                            distance(program.begin(), idx);
                    }
                }
            }
        }
    }
    // cout << "itemDFA--end" << endl;
}

void LrS::getAG()
{
    // cout << "getAG--begin" << endl;
    //首先要构建项目集规范族的DFA 此时得到了响应的 GOTO 表
    itemDFA();

    //后面进行构建 ACTION表
    //遍历项目集 规范族

    // S' -> S. ,#
    set<char> symbolBegin;
    symbolBegin.insert('#');
    Production S = Production('$', char2string(G.production[0].proBegin) + '.',
                              symbolBegin);

    for (int i = 0; i < program.size(); i++) {
        //每个项目集
        Item I = program[i];

        vector<Production>::iterator it = I.production.begin();
        for (; it != I.production.end(); it++) {
            int ppoint = (*it).proEnd.find('.');
            if (ppoint < (*it).proEnd.size() - 1) {
                char X = (*it).proEnd[ppoint + 1];
                //判断 x 是否为终结符 判断GOTO 表中是否存在  I,x
                if (G.final.find(X) != G.final.end() &&
                    GOTO.find(make_pair(i, X)) != GOTO.end()) {
                    //若为终结符，则移进 .ACTION表 划为 shift
                    int temp                = GOTO[make_pair(i, X)];
                    ACTION[make_pair(i, X)] = make_pair(shift, temp);
                }
            }
            else {
                // acc
                if ((*it) == S) {
                    ACTION[make_pair(i, '#')] = make_pair(acc, 0);
                }
                else if ((*it).proBegin != '$') {
                    // reduce
                    string temp = (*it).proEnd;
                    temp.erase(ppoint, 1);
                    for (set<char>::iterator addSymbol =
                             (*it).additionalSymbol.begin();
                         addSymbol != (*it).additionalSymbol.end();
                         addSymbol++) {
                        bool isFindInG = false;

                        Production p =
                            Production((*it).proBegin, temp, set<char>{});
                        vector<Production>::iterator itG = G.production.begin();
                        for (; itG != G.production.end(); itG++) {
                            if ((*itG).proBegin == p.proBegin &&
                                (*itG).proEnd == p.proEnd) {
                                isFindInG = true;
                                break;
                            }
                        }
                        if (isFindInG) {
                            ACTION[make_pair(i, (*addSymbol))] = make_pair(
                                reduce, distance(G.production.begin(), itG));
                        }
                    }
                }
            }
        }
    }

    if (G.final.find('@') != G.final.end()) {
        G.final.erase(G.final.find('@'));
        G.allSymbol.erase(G.allSymbol.find('@'));
    }
    G.final.insert('#');
    G.allSymbol.insert('#');
    // cout << "getAG--end" << endl;
    return;
}

void LrS::parser()
{
    bool finish = false;
    int  step   = 0;
    cout << "步骤       状态栈        符号栈        输入串       ACTION    "
            "   GOTO      "
         << endl;
    output_PARSER_S
        << "步骤       状态栈        符号栈        输入串       ACTION    "
           "   GOTO      "
        << endl;
    while (!finish) {
        cout << step << "     ";
        output_PARSER_S << step << "     ";
        showStateStack();
        cout << "     ";
        output_PARSER_S << "     ";
        showAnalyzeStack();
        cout << "     ";
        output_PARSER_S << "     ";
        showInputStack();
        cout << "     ";
        output_PARSER_S << "     ";

        int             stateStackTop = stateStack.size() - 1;
        int             inputStackTop = inputStack.size() - 1;
        pair<int, char> temp =
            make_pair(stateStack[stateStackTop], inputStack[inputStackTop]);
        //出错
        if (ACTION.find(temp) == ACTION.end()) {
            cout << "Syntactic Error" << endl;
            output_PARSER_S << "Syntactic Error" << endl;
            getError();
            break;
        }
        pair<actionState, int> actionTemp = ACTION[temp];
        //移进
        if (actionTemp.first == shift) {
            cout << "SHIFT-->" << actionTemp.second;
            output_PARSER_S << "SHIFT-->" << actionTemp.second;

            stateStack.push_back(actionTemp.second);
            analyzeStack.push_back(inputStack[inputStackTop]);
            inputStack.pop_back();
            lineStack.pop_back();
        }
        else if (actionTemp.first == reduce) {
            //规约
            Production p = G.production[actionTemp.second];
            cout << "REDUCE-->" << actionTemp.second << " : " << p.proBegin
                 << "->" << p.proEnd;
            output_PARSER_S << "REDUCE-->" << actionTemp.second << " : "
                            << p.proBegin << "->" << p.proEnd;

            if (p.proEnd != "@") {
                //从状态栈 和 分析栈 中 自栈顶向下去掉r个字符 （r 为A->X
                // X的长度）， 并把A移入到分析栈中，再把满足
                // SJ=GOTO[SI,A]的状态移入状态栈
                for (int i = 0; i < p.proEnd.size(); i++) {
                    stateStack.pop_back();
                    analyzeStack.pop_back();
                }
            }
            //输出 新增状态
            cout << "    "
                 << GOTO[make_pair(stateStack[stateStack.size() - 1],
                                   p.proBegin)];
            output_PARSER_S << "    "
                            << GOTO[make_pair(stateStack[stateStack.size() - 1],
                                              p.proBegin)];

            analyzeStack.push_back(p.proBegin);
            stateStack.push_back(
                GOTO[make_pair(stateStack[stateStack.size() - 1], p.proBegin)]);
        }
        else if (actionTemp.first == acc) {
            finish = true;

            cout << "ACC" << endl;
            output_PARSER_S << "ACC" << endl;
        }
        step++;

        cout << endl << endl;
        output_PARSER_S << endl << endl;
    }
    if (finish) {
        cout << "YES" << endl;
        output_PARSER_S << "YES" << endl;
    }
    else {
        cout << "NO";
        output_PARSER_S << "NO";
        exit(0);
    }
}

void LrS::getError()
{
    cout << "ErrorLine -> " << lineStack.back() << endl;
    output_PARSER_S << "ErrorLine -> " << lineStack.back() << endl;
    //简单纠错
    char x = analyzeStack.back();
    char y = inputStack.back();
    cout << "x : " << x << " y : " << y << endl;
    // x 为 分析栈最后一位  y 为 输入栈 最后一位

    if (x == 't' && y == 'y') {
        cout << "Error -> 缺少标识符" << endl;
        output_PARSER_S << "Error -> 缺少标识符" << endl;
    }
    if (x == 'z' && y == 't') {
        cout << "Error -> 缺少;" << endl;
        output_PARSER_S << "Error -> 缺少;" << endl;
    }
    if (x == 'z' && y == 'z') {
        cout << "Error -> 缺少;或," << endl;
        output_PARSER_S << "Error -> 缺少;或," << endl;
    }
    if (x == 'y' && y == '}') {
        cout << "Error -> 缺少;" << endl;
        output_PARSER_S << "Error -> 缺少;" << endl;
    }
    if (x == 'z' && y == 'y') {
        cout << "Error -> 缺少运算符" << endl;
        output_PARSER_S << "Error -> 缺少运算符" << endl;
    }
    if (x == 'y' && y == 't') {
        cout << "Error -> 缺少;" << endl;
        output_PARSER_S << "Error -> 缺少;" << endl;
    }
    if (x == 'y' && y == 'z') {
        cout << "Error -> 缺少算术运算符或;或," << endl;
        output_PARSER_S << "Error -> 缺少算术运算符或;或," << endl;
    }
    if (x == 'y' && y == 'y') {
        cout << "Error -> 缺少算术运算符" << endl;
        output_PARSER_S << "Error -> 缺少算术运算符" << endl;
    }

    if (x != 't' && x != 'z' && x != 'y' && !isDelimiterS(x) && y != 't' &&
        y != 'z' && y != 'y' && !isDelimiterS(y)) {
        cout << "Error -> 多余运算符" << y << endl;
        output_PARSER_S << "Error -> 多余运算符" << y << endl;
    }

    if (x != 't' && x != 'z' && x != 'y' && !isDelimiterS(x) &&
        isDelimiterS(y)) {
        cout << "Error -> 缺少常数或标识符或)" << endl;
        output_PARSER_S << "Error -> 缺少常数或标识符或)" << endl;
    }

    if (y != 't' && y != 'z' && y != 'y' && !isDelimiterS(y) &&
        isDelimiterS(x)) {
        if (y == '#') {
            cout << "Error -> 缺少 } " << endl;
            output_PARSER_S << "Error -> 缺少 } " << endl;
        }
        else {
            cout << "Error -> 缺少常数或标识符或 ( " << endl;
            output_PARSER_S << "Error -> 缺少常数或标识符或 ( " << endl;
        }
    }
}

void LrS::run()
{
    string in;
    while (getline(input_SyntacticInput_S, in) && in != "#")
        addItem(in);
    in = "";

    // G.show();
    // cout << endl;
    // cout << "getAG : " << endl;
    getAG();

    // showAFG();

    // cout << endl << "input : " << endl;
    getline(input_LexicalOutput_S, in);
    if (in == "#" || in.size() == 0)
        return;

    getInputStack(in);
    parser();
    parser_S();

    showQuad();

    // showIdent();
}

void LrS::showAFG()
{
    // FIRST集 用于中间生成
    // map<char, set<char>> FIRST;
    // ACTION表 int + char -> char + int
    // map<pair<int, char>, pair<actionState, int>> ACTION;
    // GOTO表 int + char -> int
    // map<pair<int, char>, int> GOTO;
    //     enum actionState {
    //     acc = 0,
    //     shift,
    //     reduce,
    //     err,
    // };

    // First:
    G.showFinal();

    cout << "FIRST : " << endl;
    output_FIRST_S << "FIRST : " << endl;

    map<char, set<char>>::iterator itFirst = FIRST.begin();
    for (; itFirst != FIRST.end(); itFirst++) {
        cout << (*itFirst).first << " : ";
        output_FIRST_S << (*itFirst).first << " : ";
        set<char>::iterator itFirst2 = (*itFirst).second.begin();
        for (; itFirst2 != (*itFirst).second.end(); itFirst2++) {
            cout << " " << (*itFirst2);
            output_FIRST_S << " " << (*itFirst2);
        }
        cout << endl;
        output_FIRST_S << endl;
    }
    cout << "ACTION : acc 0 shift 1 reduce 2" << endl;
    output_ACTION_S << "ACTION : acc 0 shift 1 reduce 2" << endl;

    map<pair<int, char>, pair<actionState, int>>::iterator itAction =
        ACTION.begin();
    for (; itAction != ACTION.end(); itAction++) {
        cout << (*itAction).first.first << " " << (*itAction).first.second
             << " " << (*itAction).second.first << " "
             << (*itAction).second.second << endl;
        output_ACTION_S << (*itAction).first.first << " "
                        << (*itAction).first.second << " "
                        << (*itAction).second.first << " "
                        << (*itAction).second.second << endl;
    }

    cout << "GOTO : " << endl;
    output_GOTO_S << "GOTO : " << endl;

    map<pair<int, char>, int>::iterator itGoto = GOTO.begin();
    for (; itGoto != GOTO.end(); itGoto++) {
        if (isupper((*itGoto).first.second)) {
            cout << (*itGoto).first.first << " " << (*itGoto).first.second
                 << " " << (*itGoto).second << endl;
            output_GOTO_S << (*itGoto).first.first << " "
                          << (*itGoto).first.second << " " << (*itGoto).second
                          << endl;
        }
    }
}

const char* ACTION_S = "ACTION_S.txt";
const char* FIRST_S  = "FIRST_S.txt";
const char* PARSER_S = "PARSER_S.txt";
const char* GOTO_S   = "GOTO_S.txt";
const char* QUAD_S   = "QUAD_S.txt";

void LfileOpen_S()
{
    output_ACTION_S.open(ACTION_S);
    output_FIRST_S.open(FIRST_S);
    output_PARSER_S.open(PARSER_S);
    output_GOTO_S.open(GOTO_S);
    output_QUAD_S.open(QUAD_S);
}

void LfileClose_S()
{
    output_ACTION_S.close();
    output_FIRST_S.close();
    output_PARSER_S.close();
    output_GOTO_S.close();
    output_QUAD_S.close();
}

bool isDelimiterS_S(char a)
{
    for (int i = 0; i < delimiterNumS_S; i++) {
        if (a == delimiterS_S[i]) {
            return true;
        }
    }
    return false;
}